package com.log320.huffman;

import java.util.ArrayList;
import java.util.LinkedList;
import java.io.IOException;
/**
 * Represent a node in the binary tree that is not a leaf 
 * (it does not represent a character)
 *
 */
public class BinaryComposite extends BinaryComponent{
	
	//Child nodes
	protected BinaryComponent m_comp0;
	protected BinaryComponent m_comp1;
	
	public BinaryComposite(BinaryComponent comp0, BinaryComponent comp1) {
		super(-1, -1);
		if (comp0 != null && comp1 != null)
			super.frequency = comp0.frequency+ comp1.frequency;
		
		m_comp0 = comp0;
		m_comp1 = comp1;
	}
/**
 * method that add a leaf to the tree. it recursively add composite as long as
 * there is more bit to go and than create the leaf with the caracter passed as
 * parameter
 * @param character	character represented by the leaf we want to add
 * @param bin		linked list of boolean representing huffman code for the caracter
 * @param bitToGo	bit(boolean) left in the linked list
 */
	
	public void addLeaf(int character, LinkedList<Boolean> bin, int bitToGo){
		boolean bit = bin.removeFirst();
		bitToGo--;
		if (bitToGo == 0){
			if(bit == false)
				m_comp0 = new BinaryLeaf(character, -1);
			else
				m_comp1 = new BinaryLeaf(character, -1);
		}
		else{
			if(bit == false){
				if(m_comp0 == null){
					m_comp0 = new BinaryComposite(null, null);
				}
				else
					assert m_comp0 instanceof BinaryComposite;
				
				((BinaryComposite)m_comp0).addLeaf(character, bin, bitToGo);
			}
			else{
				if(m_comp1 == null){
					m_comp1 = new BinaryComposite(null, null);
				}
				else
					assert m_comp1 instanceof BinaryComposite;
			
				((BinaryComposite)m_comp1).addLeaf(character, bin, bitToGo);
			}
		}
	}
/**
 * Used to generate an array containing all leafs (nodes representing characters)
 * with their corresponding binary codes. This implementation simply calls
 * the buildLeafArray of the two children nodes.
 */
	@Override
	public void buildLeafArray(ArrayList<BinaryCode> bitArray,LinkedList<Boolean> tempBitArray) {
		// TODO Auto-generated method stub
		
		LinkedList<Boolean> leftBitArray = (LinkedList<Boolean>)tempBitArray.clone();
		leftBitArray.add(false);
		
		LinkedList<Boolean> rightBitArray = (LinkedList<Boolean>)tempBitArray.clone();
		rightBitArray.add(true);
		
		m_comp0.buildLeafArray(bitArray, leftBitArray);
		m_comp1.buildLeafArray(bitArray, rightBitArray);
	}
/**
 * decode the stream
 * @param stream	the bitstream
 * @return value representing the value of the byte that was encoded
 */
	public int Decode(BitInputStream stream){
		try {
			if (stream.readBit() == false)
				return m_comp0.Decode(stream);
			else
				return m_comp1.Decode(stream);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
	}
	
}
